import pygame
import numpy as np
from .tile import Tile

class GameBoard:
    """游戏板类，管理方块的逻辑和状态"""
    
    def __init__(self, rows=8, cols=8, tile_size=60, max_tile_types=5):
        """
        初始化游戏板
        
        参数:
            rows: 行数
            cols: 列数
            tile_size: 方块大小（像素）
            max_tile_types: 最大方块类型数
        """
        self.rows = rows
        self.cols = cols
        self.tile_size = tile_size
        self.max_tile_types = max_tile_types
        
        # 计算游戏板尺寸
        self.width = int(cols * tile_size)
        self.height = int(rows * tile_size)
        
        # 初始化游戏板的Surface
        self.surface = pygame.Surface((self.width, self.height))
        
        # 初始化方块网格
        self.grid = [[None for _ in range(cols)] for _ in range(rows)]
        
        # 游戏状态相关
        self.selected_tile = None
        self.score = 0
        self.moves = 0
        self.is_animating = False
        self.tiles_to_remove = []
        
        # 初始化游戏板
        self.initialize_board()
        
    def initialize_board(self):
        """初始化游戏板，生成初始方块"""
        for row in range(self.rows):
            for col in range(self.cols):
                # 创建随机方块时，确保不会形成初始匹配
                valid_types = list(range(self.max_tile_types))
                
                # 检查左侧两个方块，避免水平方向的三连
                if col >= 2:
                    if self.grid[row][col-1] is not None and self.grid[row][col-2] is not None:
                        if self.grid[row][col-1].type == self.grid[row][col-2].type:
                            if self.grid[row][col-1].type in valid_types:
                                valid_types.remove(self.grid[row][col-1].type)
                
                # 检查上方两个方块，避免垂直方向的三连
                if row >= 2:
                    if self.grid[row-1][col] is not None and self.grid[row-2][col] is not None:
                        if self.grid[row-1][col].type == self.grid[row-2][col].type:
                            if self.grid[row-1][col].type in valid_types:
                                valid_types.remove(self.grid[row-1][col].type)
                
                # 如果没有有效类型，则使用任意类型
                if not valid_types:
                    valid_types = list(range(self.max_tile_types))
                    
                # 随机选择一个有效类型
                tile_type = np.random.choice(valid_types)
                self.grid[row][col] = Tile(tile_type, row, col, self.tile_size)
    
    def draw(self, surface, offset_x=0, offset_y=0):
        """
        绘制游戏板
        
        参数:
            surface: 要绘制到的pygame Surface
            offset_x: x偏移
            offset_y: y偏移
        """
        # 创建渐变背景
        gradient_rect = pygame.Surface((int(self.width), int(self.height)))
        for y in range(int(self.height)):
            # 创建从深色到稍微浅色的渐变
            color_value = 40 + int(y * 20 / self.height)
            color = (color_value, color_value, color_value + 10)
            pygame.draw.line(gradient_rect, color, (0, y), (int(self.width), y))
            
        # 在游戏板的边缘添加边框
        border_rect = pygame.Rect(0, 0, int(self.width), int(self.height))
        pygame.draw.rect(gradient_rect, (80, 80, 100), border_rect, 2, border_radius=5)
        
        # 应用背景到游戏板surface
        self.surface.blit(gradient_rect, (0, 0))
        
        # 绘制优雅的网格线
        for row in range(self.rows + 1):
            # 水平线，使用半透明淡蓝色
            line_color = (100, 120, 140, 70)
            y_pos = row * self.tile_size
            
            # 使用Surface和alpha通道以支持透明度
            line_surface = pygame.Surface((int(self.width), 1), pygame.SRCALPHA)
            line_surface.fill(line_color)
            self.surface.blit(line_surface, (0, y_pos))
            
        for col in range(self.cols + 1):
            # 垂直线，使用相同的半透明淡蓝色
            x_pos = col * self.tile_size
            line_surface = pygame.Surface((1, int(self.height)), pygame.SRCALPHA)
            line_surface.fill(line_color)
            self.surface.blit(line_surface, (x_pos, 0))
            
        # 绘制所有方块
        for row in range(self.rows):
            for col in range(self.cols):
                if self.grid[row][col]:
                    self.grid[row][col].draw(self.surface)
        
        # 将游戏板surface绘制到主surface
        surface.blit(self.surface, (offset_x, offset_y))
    
    def update(self):
        """更新游戏板状态"""
        self.is_animating = False
        
        # 更新所有方块动画
        for row in range(self.rows):
            for col in range(self.cols):
                if self.grid[row][col]:
                    # 更新方块状态，如果返回True表示方块已消除
                    if self.grid[row][col].update():
                        self.grid[row][col] = None
                    elif self.grid[row][col].is_animating():
                        self.is_animating = True
        
        # 如果有方块要移除并且没有动画在进行，开始消除过程
        if self.tiles_to_remove and not self.is_animating:
            for row, col in self.tiles_to_remove:
                if self.grid[row][col]:
                    self.grid[row][col].start_vanish_animation()
                    self.is_animating = True
            self.tiles_to_remove = []
            
        # 如果没有动画在进行，检查并填充空缺
        if not self.is_animating:
            self.fill_empty_spaces()
    
    def handle_click(self, x, y, offset_x=0, offset_y=0):
        """
        处理点击事件
        
        参数:
            x, y: 点击的坐标
            offset_x, offset_y: 游戏板的偏移量
        
        返回值:
            bool: 是否进行了有效操作
        """
        # 如果有动画在进行，忽略点击
        if self.is_animating:
            return False
            
        # 计算点击的行列（确保使用整数）
        col = int((x - offset_x) / self.tile_size)
        row = int((y - offset_y) / self.tile_size)
        
        # 检查是否点击在有效范围内
        if 0 <= row < self.rows and 0 <= col < self.cols and self.grid[row][col]:
            if self.selected_tile is None:
                # 选中第一个方块
                self.grid[row][col].selected = True
                self.selected_tile = (row, col)
            else:
                # 已经有选中的方块，检查是否相邻
                sel_row, sel_col = self.selected_tile
                
                # 清除选中状态
                self.grid[sel_row][sel_col].selected = False
                
                # 检查是否相邻
                is_adjacent = (
                    (abs(row - sel_row) == 1 and col == sel_col) or
                    (abs(col - sel_col) == 1 and row == sel_row)
                )
                
                if is_adjacent:
                    # 交换方块
                    self.swap_tiles(sel_row, sel_col, row, col)
                    self.moves += 1
                    return True
                else:
                    # 不相邻，选中新方块
                    self.grid[row][col].selected = True
                    self.selected_tile = (row, col)
                
            return True
            
        # 点击无效区域，清除选中状态
        if self.selected_tile:
            sel_row, sel_col = self.selected_tile
            self.grid[sel_row][sel_col].selected = False
            self.selected_tile = None
            return True
            
        return False
    
    def swap_tiles(self, row1, col1, row2, col2):
        """
        交换两个方块
        
        参数:
            row1, col1: 第一个方块的行列
            row2, col2: 第二个方块的行列
        """
        # 交换网格中的方块对象
        self.grid[row1][col1], self.grid[row2][col2] = self.grid[row2][col2], self.grid[row1][col1]
        
        # 更新方块的行列和位置
        if self.grid[row1][col1]:
            self.grid[row1][col1].update_position(row1, col1)
        if self.grid[row2][col2]:
            self.grid[row2][col2].update_position(row2, col2)
            
        # 检查是否形成匹配
        matches = self.check_matches()
        
        # 如果没有匹配，交换回来
        if not matches:
            self.grid[row1][col1], self.grid[row2][col2] = self.grid[row2][col2], self.grid[row1][col1]
            
            if self.grid[row1][col1]:
                self.grid[row1][col1].update_position(row1, col1)
            if self.grid[row2][col2]:
                self.grid[row2][col2].update_position(row2, col2)
                
        self.selected_tile = None
    
    def check_matches(self):
        """
        检查整个游戏板的匹配
        
        返回值:
            bool: 是否有匹配
        """
        matches = []
        
        # 检查水平匹配
        for row in range(self.rows):
            for col in range(self.cols - 2):
                if (self.grid[row][col] and self.grid[row][col+1] and self.grid[row][col+2] and
                    self.grid[row][col].type == self.grid[row][col+1].type == self.grid[row][col+2].type):
                    
                    # 找到匹配的起点和终点
                    start_col = col
                    end_col = col + 2
                    
                    # 向右扩展匹配
                    for c in range(col + 3, self.cols):
                        if self.grid[row][c] and self.grid[row][c].type == self.grid[row][col].type:
                            end_col = c
                        else:
                            break
                    
                    # 添加所有匹配的方块
                    for c in range(start_col, end_col + 1):
                        matches.append((row, c))
        
        # 检查垂直匹配
        for col in range(self.cols):
            for row in range(self.rows - 2):
                if (self.grid[row][col] and self.grid[row+1][col] and self.grid[row+2][col] and
                    self.grid[row][col].type == self.grid[row+1][col].type == self.grid[row+2][col].type):
                    
                    # 找到匹配的起点和终点
                    start_row = row
                    end_row = row + 2
                    
                    # 向下扩展匹配
                    for r in range(row + 3, self.rows):
                        if self.grid[r][col] and self.grid[r][col].type == self.grid[row][col].type:
                            end_row = r
                        else:
                            break
                    
                    # 添加所有匹配的方块
                    for r in range(start_row, end_row + 1):
                        matches.append((r, col))
        
        # 删除重复的匹配
        matches = list(set(matches))
        
        if matches:
            # 计算分数: 基础分 + 额外连击分
            match_score = len(matches) * 10
            combo_bonus = max(0, len(matches) - 3) * 5
            self.score += match_score + combo_bonus
            
            # 将匹配的方块添加到待移除列表
            self.tiles_to_remove.extend(matches)
            return True
            
        return False
    
    def fill_empty_spaces(self):
        """填充空缺的方块位置"""
        has_changes = False
        
        # 处理方块下落
        for col in range(self.cols):
            # 从底部向上处理每一列
            empty_row = None
            
            for row in range(self.rows - 1, -1, -1):
                if self.grid[row][col] is None and empty_row is None:
                    empty_row = row
                elif self.grid[row][col] is not None and empty_row is not None:
                    # 移动方块到空位置
                    self.grid[empty_row][col] = self.grid[row][col]
                    self.grid[row][col] = None
                    self.grid[empty_row][col].update_position(empty_row, col)
                    
                    # 更新空位置
                    empty_row -= 1
                    has_changes = True
            
            # 在顶部生成新方块
            for row in range(self.rows):
                if self.grid[row][col] is None:
                    tile_type = Tile.get_random_type(self.max_tile_types - 1)
                    
                    # 创建新方块，并设置初始位置在顶部之上
                    self.grid[row][col] = Tile(tile_type, -1, col, self.tile_size)
                    self.grid[row][col].update_position(row, col)
                    has_changes = True
        
        # 检查新的匹配
        if has_changes and not self.is_animating:
            self.check_matches()
            
    def is_game_over(self):
        """
        检查是否还有可能的移动
        
        返回值:
            bool: 如果没有可能的移动，返回True
        """
        # 检查每一个可能的移动
        for row in range(self.rows):
            for col in range(self.cols):
                # 检查向右交换
                if col < self.cols - 1:
                    # 交换
                    self.grid[row][col], self.grid[row][col+1] = self.grid[row][col+1], self.grid[row][col]
                    
                    # 检查是否有匹配
                    has_match = self.check_potential_matches()
                    
                    # 交换回来
                    self.grid[row][col], self.grid[row][col+1] = self.grid[row][col+1], self.grid[row][col]
                    
                    if has_match:
                        return False
                
                # 检查向下交换
                if row < self.rows - 1:
                    # 交换
                    self.grid[row][col], self.grid[row+1][col] = self.grid[row+1][col], self.grid[row][col]
                    
                    # 检查是否有匹配
                    has_match = self.check_potential_matches()
                    
                    # 交换回来
                    self.grid[row][col], self.grid[row+1][col] = self.grid[row+1][col], self.grid[row][col]
                    
                    if has_match:
                        return False
        
        return True
    
    def check_potential_matches(self):
        """
        检查当前游戏板是否有潜在的匹配（不实际消除）
        
        返回值:
            bool: 是否有匹配
        """
        # 检查水平匹配
        for row in range(self.rows):
            for col in range(self.cols - 2):
                if (self.grid[row][col] and self.grid[row][col+1] and self.grid[row][col+2] and
                    self.grid[row][col].type == self.grid[row][col+1].type == self.grid[row][col+2].type):
                    return True
        
        # 检查垂直匹配
        for col in range(self.cols):
            for row in range(self.rows - 2):
                if (self.grid[row][col] and self.grid[row+1][col] and self.grid[row+2][col] and
                    self.grid[row][col].type == self.grid[row+1][col].type == self.grid[row+2][col].type):
                    return True
                    
        return False
        
    def shuffle_board(self):
        """打乱游戏板"""
        # 收集所有方块类型
        types = []
        for row in range(self.rows):
            for col in range(self.cols):
                if self.grid[row][col]:
                    types.append(self.grid[row][col].type)
        
        # 打乱类型
        np.random.shuffle(types)
        
        # 重新分配类型
        index = 0
        for row in range(self.rows):
            for col in range(self.cols):
                if self.grid[row][col]:
                    self.grid[row][col].type = types[index]
                    self.grid[row][col].color = Tile.COLORS.get(types[index], (150, 150, 150))
                    index += 1
                    
        # 确保没有初始匹配
        while self.check_matches():
            self.shuffle_board() 